package cas;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * 版本升级
 *
 * @author dengzhiyuan
 * @version 1.0
 * @time 2021/3/15 18:51
 */
public class VisitTimesV2 {

    /**
     * volatile 主存中拉去
     */
    volatile static int count = 0;

    public static void request() throws InterruptedException{
        TimeUnit.MILLISECONDS.sleep(5);
        /**
         * Q:分析一下问题出在那里
         * A:count++  操作实际上是由3步来完成的（jvm执行引擎）
         * 1.获取count的值，记做A:A=count
         * 2.将A值+1，得到B:B=A+1
         * 3.将B值赋值给count
         */
        int expectCount;
        while (!compareAndSwap(expectCount = getCount(), expectCount+1)){}
    }

    /**
     * 
     * @author dengzhiyuan
     * @version 1.0
     * @time 2021/3/22 11:45
     * @param expectCount 期望值
     * @param newCount 需要给count赋值的新值
     * @return 
     */
    public static synchronized  boolean compareAndSwap(int expectCount,int newCount){
        //判断count当前值是否和期望值一致，如果一致将newCount赋值给count
        if(getCount() == expectCount){
            count = newCount;
            return true;
        }
        return false;
    }

    public static int getCount(){
        return  count;
    }

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        int threadSize = 100;
        CountDownLatch countDownLatch = new CountDownLatch(threadSize);
        for (int t = 0; t < threadSize; t++) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int i = 0; i < 10; i++) {
                            request();
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            });
            thread.start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+ "，耗时间="+(System.currentTimeMillis()-startTime)+",count="+getCount());
    }



}
